package com.sugar.psych.assessment.module.business.service.usertreeholechatrecord;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sugar.psych.assessment.framework.mybatis.core.dataobject.BaseDO;
import com.sugar.psych.assessment.module.business.config.websocket.WebSocketService;
import com.sugar.psych.assessment.module.business.controller.app.usertreeholechatrecord.vo.AiChatMessageReqVO;
import com.sugar.psych.assessment.module.business.controller.app.usertreeholechatrecord.vo.AiChatMessageRespVO;
import com.sugar.psych.assessment.module.business.controller.app.usertreeholechatrecord.vo.AiChatRecordSimpleRespVO;
import com.sugar.psych.assessment.module.business.dal.dataobject.usertreeholechatrecord.UserTreeHoleChatDO;
import com.sugar.psych.assessment.module.business.dal.mysql.usertreeholechatrecord.UserTreeHoleChatMapper;
import com.sugar.psych.assessment.module.business.util.DeepSeekUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import com.sugar.psych.assessment.module.business.controller.admin.usertreeholechatrecord.vo.*;
import com.sugar.psych.assessment.module.business.dal.dataobject.usertreeholechatrecord.UserTreeHoleChatRecordDO;
import com.sugar.psych.assessment.framework.common.pojo.PageResult;
import com.sugar.psych.assessment.framework.common.pojo.PageParam;
import com.sugar.psych.assessment.framework.common.util.object.BeanUtils;

import com.sugar.psych.assessment.module.business.dal.mysql.usertreeholechatrecord.UserTreeHoleChatRecordMapper;
import reactor.core.publisher.Flux;

import static com.sugar.psych.assessment.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.sugar.psych.assessment.module.business.enums.ErrorCodeConstants.*;

/**
 * 树洞AI聊天会话 Service 实现类
 *
 * @author Ysugar
 */
@Slf4j
@Service
@Validated
public class UserTreeHoleChatRecordServiceImpl implements UserTreeHoleChatRecordService {

    @Resource
    private UserTreeHoleChatRecordMapper userTreeHoleChatRecordMapper;
    @Resource
    private UserTreeHoleChatMapper userTreeHoleChatMapper;
    @Resource
    private WebSocketService webSocketService;

    @Override
    public Long createUserTreeHoleChatRecord(UserTreeHoleChatRecordSaveReqVO createReqVO) {
        // 插入
        UserTreeHoleChatRecordDO userTreeHoleChatRecord = BeanUtils.toBean(createReqVO, UserTreeHoleChatRecordDO.class);
        userTreeHoleChatRecordMapper.insert(userTreeHoleChatRecord);
        // 返回
        return userTreeHoleChatRecord.getId();
    }

    @Override
    public void updateUserTreeHoleChatRecord(UserTreeHoleChatRecordSaveReqVO updateReqVO) {
        // 校验存在
        validateUserTreeHoleChatRecordExists(updateReqVO.getId());
        // 更新
        UserTreeHoleChatRecordDO updateObj = BeanUtils.toBean(updateReqVO, UserTreeHoleChatRecordDO.class);
        userTreeHoleChatRecordMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUserTreeHoleChatRecord(Long id) {
        // 校验存在
        validateUserTreeHoleChatRecordExists(id);
        // 删除
        userTreeHoleChatRecordMapper.deleteById(id);

        // 删除子表
        deleteUserTreeHoleChatByRecordId(id);
    }

    @Override
        @Transactional(rollbackFor = Exception.class)
    public void deleteUserTreeHoleChatRecordListByIds(List<Long> ids) {
        // 校验存在
        validateUserTreeHoleChatRecordExists(ids);
        // 删除
        userTreeHoleChatRecordMapper.deleteByIds(ids);
    
    // 删除子表
            deleteUserTreeHoleChatByRecordIds(ids);
    }

    private void validateUserTreeHoleChatRecordExists(List<Long> ids) {
        List<UserTreeHoleChatRecordDO> list = userTreeHoleChatRecordMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(USER_TREE_HOLE_CHAT_RECORD_NOT_EXISTS);
        }
    }

    private void validateUserTreeHoleChatRecordExists(Long id) {
        if (userTreeHoleChatRecordMapper.selectById(id) == null) {
            throw exception(USER_TREE_HOLE_CHAT_RECORD_NOT_EXISTS);
        }
    }

    @Override
    public UserTreeHoleChatRecordDO getUserTreeHoleChatRecord(Long id) {
        return userTreeHoleChatRecordMapper.selectById(id);
    }

    @Override
    public PageResult<UserTreeHoleChatRecordDO> getUserTreeHoleChatRecordPage(UserTreeHoleChatRecordPageReqVO pageReqVO) {
        return userTreeHoleChatRecordMapper.selectPage(pageReqVO);
    }

    // ==================== 子表（树洞AI聊天消息） ====================

    @Override
    public PageResult<UserTreeHoleChatDO> getUserTreeHoleChatPage(PageParam pageReqVO, Long recordId) {
        return userTreeHoleChatMapper.selectPage(pageReqVO, recordId);
    }

    @Override
    public Long createUserTreeHoleChat(UserTreeHoleChatDO userTreeHoleChat) {
        userTreeHoleChatMapper.insert(userTreeHoleChat);
        return userTreeHoleChat.getId();
    }

    @Override
    public void updateUserTreeHoleChat(UserTreeHoleChatDO userTreeHoleChat) {
        // 校验存在
        validateUserTreeHoleChatExists(userTreeHoleChat.getId());
        // 更新
        userTreeHoleChat.clean(); // 解决更新情况下：updateTime 不更新
        userTreeHoleChatMapper.updateById(userTreeHoleChat);
    }

    @Override
    public void deleteUserTreeHoleChat(Long id) {
        // 删除
        userTreeHoleChatMapper.deleteById(id);
    }

	@Override
	public void deleteUserTreeHoleChatListByIds(List<Long> ids) {
        // 删除
        userTreeHoleChatMapper.deleteByIds(ids);
	}

    @Override
    public UserTreeHoleChatDO getUserTreeHoleChat(Long id) {
        return userTreeHoleChatMapper.selectById(id);
    }

    private void validateUserTreeHoleChatExists(Long id) {
        if (userTreeHoleChatMapper.selectById(id) == null) {
            throw exception(USER_TREE_HOLE_CHAT_NOT_EXISTS);
        }
    }

    private void deleteUserTreeHoleChatByRecordId(Long recordId) {
        userTreeHoleChatMapper.deleteByRecordId(recordId);
    }

    private void deleteUserTreeHoleChatByRecordIds(List<Long> recordIds) {
        userTreeHoleChatMapper.deleteByRecordIds(recordIds);
    }

    @Override
    public Long createAiChatRecord(Long loginUserId) {
        UserTreeHoleChatRecordDO recordDO = new UserTreeHoleChatRecordDO();
        recordDO.setUserId(loginUserId).setTitle("新会话");
        userTreeHoleChatRecordMapper.insert(recordDO);
        return recordDO.getId();
    }

    @Override
    public void sendChatMessageStream(AiChatMessageReqVO sendReqVO, Long userId) {
        Long recordId = sendReqVO.getId();
        UserTreeHoleChatRecordDO record = userTreeHoleChatRecordMapper.selectById(recordId);
        if (Objects.isNull(record))
            throw exception(USER_TREE_HOLE_CHAT_RECORD_NOT_EXISTS);

        // 插入用户消息
        UserTreeHoleChatDO userMessage = new UserTreeHoleChatDO();
        String content = sendReqVO.getContent();
        userMessage.setMsgRole(false).setRecordId(recordId).setContent(content);
        userTreeHoleChatMapper.insert(userMessage);

        // 更新会话标题
        userTreeHoleChatRecordMapper.update(UserTreeHoleChatRecordDO::getId, recordId, UserTreeHoleChatRecordDO::getTitle, content);

        Flux<String> steamResponse = DeepSeekUtil.chatStream(sendReqVO.getContent());

        StringBuffer contentBuffer = new StringBuffer();
        steamResponse.doOnComplete(() -> {
            // 插入AI回复消息
            userTreeHoleChatMapper.insert(new UserTreeHoleChatDO().setMsgRole(true).setRecordId(recordId).setContent(contentBuffer.toString()));
        }).doOnError(throwable -> {
            log.error("[appSendChatMessageStream][userId({}) sendReqVO({}) 发生异常]", userId, sendReqVO, throwable);
            // 插入AI回复消息
            userTreeHoleChatMapper.insert(new UserTreeHoleChatDO().setMsgRole(true).setRecordId(recordId).setContent(contentBuffer.toString()));

            webSocketService.sendMsgOne("AI 回复异常......", String.valueOf(userId), String.valueOf(recordId));
            webSocketService.sendMsgOne("[DONE]", String.valueOf(userId), String.valueOf(recordId));
        }).subscribe(responseJsonStr -> {
            if (!"[DONE]".equals(responseJsonStr)){
                JSONObject respJson = JSONUtil.parseObj(responseJsonStr);
                JSONArray choices = respJson.getJSONArray("choices");
                JSONObject choice = JSONUtil.parseObj(choices.get(0));
                String newContent = StrUtil.nullToDefault(choice.getJSONObject("delta").getStr("content"), "");
                contentBuffer.append(newContent);
                webSocketService.sendMsgOne(newContent, String.valueOf(userId), String.valueOf(recordId));
            }else
                webSocketService.sendMsgOne(responseJsonStr, String.valueOf(userId), String.valueOf(recordId));
        });
    }

    @Override
    public List<AiChatMessageRespVO> getAiChatRecord(Long id) {
        return BeanUtils.toBean(userTreeHoleChatMapper.selectList(Wrappers.<UserTreeHoleChatDO>lambdaQuery()
                .eq(UserTreeHoleChatDO::getRecordId, id)
                .orderByAsc(BaseDO::getCreateTime)), AiChatMessageRespVO.class);
    }

    @Override
    public PageResult<AiChatRecordSimpleRespVO> appGetAiChatRecordPage(PageParam pageParam, Long loginUserId) {
        return BeanUtils.toBean(userTreeHoleChatRecordMapper.selectPage(pageParam, Wrappers.<UserTreeHoleChatRecordDO>lambdaQuery()
                .eq(UserTreeHoleChatRecordDO::getUserId, loginUserId).orderByDesc(BaseDO::getCreateTime)), AiChatRecordSimpleRespVO.class);
    }

    @Override
    public void delAiChatRecord(Long loginUserId, Long id) {
        userTreeHoleChatRecordMapper.delete(Wrappers.<UserTreeHoleChatRecordDO>lambdaQuery()
                .eq(UserTreeHoleChatRecordDO::getId, id)
                .eq(UserTreeHoleChatRecordDO::getUserId, loginUserId));
        userTreeHoleChatMapper.delete(Wrappers.<UserTreeHoleChatDO>lambdaQuery()
                .eq(UserTreeHoleChatDO::getRecordId, id));
    }

}